home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Online / opennap / metaserver.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  7KB  |  275 lines

  1. /* Copyright (C) 2000-1 drscholl@users.sourceforge.net
  2.    This is free software distributed under the terms of the
  3.    GNU Public License.  See the file COPYING for details.
  4.  
  5.    $Id: metaserver.c,v 1.18 2001/02/15 08:39:45 drscholl Exp $ */
  6.  
  7. /* a simple napster metaserver.  redirects clients to a specific set of
  8.    servers */
  9.  
  10. /* Modified 29/05/01 : Added include "confdefs.h" since we are not using the
  11.       for Amiga port : CONFIGURE script
  12.  
  13.                        Added define for htons(), which is not defined in the
  14.                        Amiga GCC 2.7.0 includes
  15.  
  16.                        Added value for __auto_socket_vers to permit automatic
  17.                        opening/closing of bsdsocket.library by socket.o
  18.  
  19.                        Added include "extrasocket.h" with inlines for a few
  20.                        bsdsocket.library functions not emulated by ixemul
  21.  
  22.                        Removed openlog() and closelog() calls, not needed by
  23.                        bsdsocket.library
  24.  
  25.             30/05/01 : Added varargs stub syslog() outside extrasocket.h. I
  26.                        intended to have this in extrasocket.h itself, but in
  27.                        another file there is a conflicting declaration of
  28.                        syslog().
  29. */
  30.  
  31. #include "confdefs.h"
  32.  
  33. #define htons(x) (x)
  34.  
  35. unsigned long __auto_socket_vers = 4;
  36.  
  37. #include <unistd.h>
  38. #include <signal.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <stdio.h>
  42. #include <limits.h>
  43. #include <sys/socket.h>
  44. #include <netinet/in.h>
  45. #include <arpa/inet.h>
  46. #if HAVE_POLL
  47. #include <sys/poll.h>
  48. #endif /* HAVE_POLL */
  49. #include <syslog.h>
  50.  
  51. #include "extrasocket.h"
  52.  
  53. /* varargs stub for syslog() */
  54.  
  55. void syslog(int level, const char * format, ...)
  56. {
  57.     vsyslog(level, format, (&format) + 1);
  58. }
  59.  
  60. #ifdef __CYGWIN__
  61. extern char *optarg;
  62. extern int optind;
  63. #endif
  64.  
  65. char    metafile[_POSIX_PATH_MAX];
  66. char   *hosts[64];
  67. int     numhosts = 0;
  68. volatile int sig_meta = 0;
  69.  
  70. #ifndef HAVE_SOCKLEN_T
  71. typedef unsigned int socklen_t;
  72. #endif
  73.  
  74. static void
  75. handler (int sig)
  76. {
  77.     if (sig == SIGHUP)
  78.         sig_meta++;
  79. }
  80.  
  81. static void
  82. usage (void)
  83. {
  84.     puts
  85.         ("usage: metaserver [ -fsv ] [ -c CONFIG ] [ -l IP ] [ -p <port> ] [ host:port ... ]");
  86.     puts ("  -c CONFIG  use list of servers in file CONFIG");
  87.     puts ("  -f         run the metaserver in the background");
  88.     puts ("  -v         display version number and exit");
  89.     puts ("  -l IP              listen only on interface for IP");
  90.     puts ("  -p <port>  listen for connection on <port> (default is 8875)");
  91.     puts ("  -s         disable syslog messages");
  92.     puts ("\n  if no arguments are given, defaults to 127.0.0.1:8888");
  93.     exit (1);
  94. }
  95.  
  96. static void
  97. read_metafile (char *filename)
  98. {
  99.     char    buffer[90];
  100.  
  101.     FILE   *fp;
  102.  
  103.     fp = fopen (filename, "r");
  104.     if (!fp)
  105.         return;
  106.     while (fgets (buffer, sizeof (buffer) - 1, fp))
  107.     {
  108.         buffer[strlen (buffer) - 1] = 0;
  109.         if (strlen (buffer) > 0 && buffer[0] != '#')
  110.             hosts[numhosts++] = strdup (buffer);
  111.     }
  112.     fclose (fp);
  113. }
  114.  
  115. int
  116. main (int argc, char **argv)
  117. {
  118.     struct sockaddr_in sin;
  119.     int     i, s, f, port = 8875;
  120.     int     location = 0;
  121.     int     sys_log = 1;
  122.     int     background = 0;
  123.  
  124. #if HAVE_POLL
  125.     struct pollfd ufd;
  126. #else
  127.     fd_set  set;
  128. #endif /* HAVE_POLL */
  129.     socklen_t sinsize;
  130.     struct sigaction sa;
  131.     unsigned int iface = INADDR_ANY;
  132.  
  133.     metafile[0] = 0;
  134.  
  135.     while ((i = getopt (argc, argv, "hfl:vp:c:s")) != EOF)
  136.     {
  137.         switch (i)
  138.         {
  139.         case 'l':
  140.             iface = inet_addr (optarg);
  141.             break;
  142.         case 'p':
  143.             port = atoi (optarg);
  144.             break;
  145.         case 'c':
  146.             strcpy (metafile, optarg);
  147.             break;
  148.         case 'f':
  149.             background ^= 1;
  150.             break;
  151.         case 's':
  152.             sys_log ^= 1;
  153.             break;
  154.         case 'v':
  155.             printf ("%s metaserver version %s\n", PACKAGE, VERSION);
  156.             exit (1);
  157.         default:
  158.             usage ();
  159.         }
  160.     }
  161.  
  162.     /* read in the host list */
  163.     if (!metafile[0])
  164.     {
  165.         if (!argv[optind])
  166.             hosts[numhosts++] = strdup ("127.0.0.1:8888");      /* use default host */
  167.         else
  168.         {
  169.             while (argv[optind])
  170.             {
  171.                 hosts[numhosts++] = strdup (argv[optind]);
  172.                 optind++;
  173.             }
  174.         }
  175.     }
  176.     else
  177.         read_metafile (metafile);
  178.  
  179.     /* set some signal handlers so we can shut down gracefully */
  180.     memset (&sa, 0, sizeof (sa));
  181.     sa.sa_handler = handler;
  182.     sigaction (SIGINT, &sa, 0);
  183.     sigaction (SIGTERM, &sa, 0);
  184.  
  185. #ifndef __CYGWIN__
  186.     sa.sa_flags = SA_RESTART;
  187. #endif
  188.     sigaction (SIGHUP, &sa, NULL);
  189.  
  190.     memset (&sin, 0, sizeof (sin));
  191.     sin.sin_port = htons (port);
  192.     sin.sin_family = AF_INET;
  193.     sin.sin_addr.s_addr = iface;
  194.  
  195.     s = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
  196.     if (s < 0)
  197.     {
  198.         perror ("socket");
  199.         exit (1);
  200.     }
  201.     if (bind (s, (struct sockaddr *) &sin, sizeof (sin)) < 0)
  202.     {
  203.         perror ("bind");
  204.         exit (1);
  205.     }
  206.     if (listen (s, 50) < 0)
  207.     {
  208.         perror ("listen");
  209.         exit (1);
  210.     }
  211.  
  212.     if (background && fork ())
  213.         _exit (0);
  214.  
  215. /*    if (sys_log)
  216.         openlog ("metaserver", LOG_PID, LOG_LOCAL6); */
  217.  
  218.     location = 0;
  219. #if HAVE_POLL
  220.     memset (&ufd, 0, sizeof (ufd));
  221.     ufd.fd = s;
  222.     ufd.events = POLLIN | POLLHUP;
  223. #endif /* HAVE_POLL */
  224.     for (;;)
  225.     {
  226. #if HAVE_POLL
  227.         i = poll (&ufd, 1, -1);
  228. #else
  229.         FD_ZERO (&set);
  230.         FD_SET (s, &set);
  231.         i = select (s + 1, &set, 0, 0, 0);
  232. #endif /* HAVE_POLL */
  233.         if (i == -1)
  234.         {
  235.             /* re-read configuration files */
  236.             if (sig_meta)
  237.             {
  238.                 for (i = 0; i < numhosts; i++)
  239.                     free (hosts[i]);
  240.                 numhosts = 0;
  241.                 location = 0;
  242.                 sig_meta = 0;
  243.                 read_metafile (metafile);
  244.                 continue;
  245.             }
  246.             perror (
  247. #if HAVE_POLL
  248.                        "poll"
  249. #else
  250.                        "select"
  251. #endif
  252.                 );
  253.             break;
  254.         }
  255.  
  256.         sinsize = sizeof (sin);
  257.         f = accept (s, (struct sockaddr *) &sin, &sinsize);
  258.         if (f < 0)
  259.         {
  260.             perror ("accept");
  261.             break;
  262.         }
  263.         write (f, hosts[location], strlen (hosts[location]));
  264.         write (f, "\n", 1);
  265.         if (sys_log)
  266.             syslog (LOG_ERR, "Redirecting %s to %s", inet_ntoa (sin.sin_addr),
  267.                     hosts[location]);
  268.         location = (location + 1) % numhosts;
  269.         close (f);
  270.     }
  271.     close (s);
  272. /*    closelog (); */
  273.     exit (0);
  274. }
  275.